home *** CD-ROM | disk | FTP | other *** search
- ; EX9_4.asm
- ;
- ; Hardware-based software timing loop example.
-
- .xlist
- include stdlib.a
- includelib stdlib.lib
- .list
-
- ; Location of BIOS variables:
-
- RTC textequ <es:[6ch]> ;Real Time Clock variable.
-
-
- dseg segment para public 'data'
-
-
- ; Dummy is a variable the timing loop compares against itself to match
- ; the timing in the InitDelay routine.
-
- Dummy word 0
-
-
- ; Timed value is an empirically determined constant which provides a
- ; suitable delay on whatever machine we are running on. The program
- ; computes a reasonable value for this variable.
-
- TimerValue dword 0
-
-
- dseg ends
-
-
- cseg segment para public 'code'
- assume cs:cseg, ds:dseg
-
-
- wp textequ <word ptr>
-
-
- ; Initialize the TimerValue variable that contains the number of loop
- ; interations for a 1/18th second delay.
-
- InitDelay proc
- push es
- push ax
-
- ; Okay, let's see how long it takes to count down 1/18th of a second.
- ; RTC is a magic location in the BIOS variables (segment 40h) which
- ; the Real Time Clock code increments every 55 ms (about 1/18.2 secs).
- ; This code waits for this location to change, then it counts off how
- ; long it takes to change again. By executing that same loop again
- ; we can get (roughly) equivalent time delays on two separate machines.
-
-
- mov ax, 40h ;Segment address of BIOS vars.
- mov es, ax
- mov ax, RTC ;Wait for timer to change.
- RTCMustChange: cmp ax, RTC
- je RTCMustChange
-
- ; Okay, begin timing the number of iterations it takes for an 18th of a
- ; second to pass. The align directive ensures that this loop and Delay's
- ; corresponding loop both fall on the same cache line boundary.
-
- mov wp TimerValue, 0
- mov wp TimerValue+2, 0
- mov ax, RTC
-
- align 16
-
- TimeRTC: cmp ax, RTC
- jne TimerDone
-
- sub wp TimerValue, 1
- sbb wp TimerValue+2, 0
- jne TimeRTC
- cmp wp TimerValue, 0
- jne TimeRTC
-
- ; Negate the count down value and decrement it to compute the number
- ; of times the delay loop must repeat the loop above.
-
- TimerDone: neg wp TimerValue+2 ;32-bit negate of
- neg wp TimerValue ; TimerValue.
- sbb wp TimerValue+2, 0
-
- pop ax
- pop es
- ret
- InitDelay endp
-
-
-
-
-
-
- ; Delay- This routine delays for roughly a fixed time period on
- ; any machine, regardless of CPU or clock rate (May vary by
- ; a factor of two or so, but it not as sensitive to CPU
- ; speed as a simple LOOP instr).
-
- Delay proc
- push es
- push ax
-
- mov ax, dseg
- mov es, ax
-
- push wp TimerValue+2 ;Save these values
- push wp TimerValue ; so we can modify them
- mov ax, Dummy ;Compare this with itself.
-
- align 16
-
- TimeRTC: cmp ax, es:Dummy
- jne DelayDone ;Never taken.
-
- sub wp TimerValue, 1
- sbb wp TimerValue+2, 0
- jne TimeRTC
- cmp wp TimerValue, 0
- jne TimeRTC
-
-
- DelayDone:
- pop wp TimerValue
- pop wp TimerValue+2
- pop ax
- pop es
- ret
- Delay endp
-
-
-
-
- Main proc
- mov ax, dseg
- mov ds, ax
- mov es, ax
-
-
- call InitDelay
-
- printf
- byte cr,lf
- byte "Hardware Based Software delay loop test",cr,lf
- byte "---------------------------------------",cr,lf,lf
- byte "Delay factor: %ld",cr,lf
- byte cr,lf
- byte "Press any key to begin an 11 second delay "
- byte "(approx).",0
- dword TimerValue
-
- getc
- putcr
- mov cx, 200 ;55 msec * 200 = 11 sec.
- Delay18: call Delay
- loop Delay18
-
- print
- byte cr,lf
- byte "Delay complete.",cr,lf
- byte cr,lf
- byte "If you have a turbo button on your PC, press it "
- byte "now to see the effect",cr,lf
- byte "of clock speed on a software delay loop.",cr,lf
- byte "Press any key to start timing delay.",0
-
- getc
- putcr
- mov cx, 200 ;55 msec * 200 = 11 sec.
- Delay18a: call Delay
- loop Delay18a
-
- print
- byte cr,lf
- byte "Delay Complete",cr,lf,0
-
-
-
-
- Quit: ExitPgm ;DOS macro to quit program.
- Main endp
-
- cseg ends
-
-
-
- sseg segment para stack 'stack'
- stk db 1024 dup ("stack ")
- sseg ends
-
-
- zzzzzzseg segment para public 'zzzzzz'
- LastBytes db 16 dup (?)
- zzzzzzseg ends
- end Main
-